https://github.com/catboost/tutorials/blob/master/python_tutorial.ipynb
CatBoostClassifier sam koduje sobie zmienne tekstowe kategoryczne na zmienne kategoryczne wyrażone numerycznie. Jeżeli sami przeprowadzimy codowanie i zakodujemy zmienne kategoryczne na format cyfrowy, wyniki naszych modeli będą takie same (przynajmniej takie jest moje doświadczenie). Aby przeprowadzić eksperyment i przetestować model CatBoostClassifier bez wskazania na zmienne kategoryczne (cat_features) oraz ze wskazaniem na zmienne musimy sami zakodoać tekstowe zmienne kategoryczne na format cyfrowy. W przeciwnym razie gdy będziemy mieli zmienne tekstowe a nie wskarzemy CatBoostClassifier że to zmienne kategoryczne, wyskoczy nam błąd.
## colorful prints
def black(text):
print('\033[30m', text, '\033[0m', sep='')
def red(text):
print('\033[31m', text, '\033[0m', sep='')
def green(text):
print('\033[32m', text, '\033[0m', sep='')
def yellow(text):
print('\033[33m', text, '\033[0m', sep='')
def blue(text):
print('\033[34m', text, '\033[0m', sep='')
def magenta(text):
print('\033[35m', text, '\033[0m', sep='')
def cyan(text):
print('\033[36m', text, '\033[0m', sep='')
def gray(text):
print('\033[90m', text, '\033[0m', sep='')
inny sposób na załadowanie tych samych danych o Tytaniku.
from catboost.datasets import titanic
import numpy as np
import pandas as pd
train_df, test_df = titanic()
train_df.head()
metoda pokazuje tylko te zmienna, w których brakuje danych.
null_value_stats = train_df.isnull().sum(axis=0)
null_value_stats[null_value_stats != 0]
train_df.fillna(-777, inplace=True)
train_df.fillna(-777, inplace=True)
X = train_df.drop('Survived', axis=1)
y = train_df.Survived
Zostały wybrane takie kolumny jako kolumny zmiennych kategorycznych.
print(X.dtypes)
categorical_features_indices = np.where(X.dtypes != np.float)[0]
categorical_features_indices
PPS = categorical_features_indices
KOT_MIC = dict(zip(train_df, PPS))
KOT_sorted_keys_MIC = sorted(KOT_MIC, key=KOT_MIC.get, reverse=True)
for r in KOT_sorted_keys_MIC:
print (r, KOT_MIC[r])
Można też użyć mojego sposobu na identyfikację zmiennych kategorycznych. Tutaj mamy nazwiska i kabiny więc ten sposób idetyfikacji zmiennych kategorycznych nie będzie właściwy.
import numpy as np
categorical_fuX = np.where(train_df.nunique() <8) [0]
categorical_fuX
from sklearn.model_selection import train_test_split
X_train, X_validation, y_train, y_validation = train_test_split(X, y, train_size=0.75, random_state=42)
X_train.head(3)
y_train.value_counts(dropna = False, normalize=True).plot(kind='pie')
Teraz stwórzmy sam model: poszlibyśmy tutaj z parametrami domyślnymi (ponieważ zapewniają one naprawdę dobrą linię bazową prawie przez cały czas), jedyną rzeczą, którą chcielibyśmy tutaj określić, jest parametr custom_loss, ponieważ dałoby to nam możliwość zobaczenia co się dzieje pod względem tego wskaźnika konkurencji - dokładności, a także możliwości obserwowania utraty logów, ponieważ byłoby to bardziej płynne w przypadku zestawu danych o takim rozmiarze.
from catboost import CatBoostClassifier, Pool, cv
from sklearn.metrics import accuracy_score
Optymalizacja pod kontem powierzchni AUC.
model = CatBoostClassifier(
custom_loss=['Accuracy'],
random_seed=42,
logging_level='Silent'
)
model.fit(
X_train, y_train,
cat_features=categorical_features_indices,
eval_set=(X_validation, y_validation),
# logging_level='Verbose', # you can uncomment this for text output
plot=True
);
Jak widać, można zobaczyć, jak nasz model uczy się na podstawie pełnych wyników lub ładnych wykresów (osobiście zdecydowanie wybrałbym drugą opcję - po prostu sprawdź te wykresy: możesz na przykład powiększyć obszary zainteresowania!)
Dzięki temu możemy zobaczyć, że najlepsza wartość dokładności 0,8340 (na zestawie walidacyjnym) została osiągnięta na 157 etapie wzmocnienia.
Żeby to zobaczyć trzeba kliknąć na Accuracy i stanąć myszą na linii ciągłej (oznaczającej zmienne testowe) nie linii przerywanej(dane treningowe)Wartość accurace wysokości 0.834 osiąga u mnie przy 451 petli. To miejsce gdzie jest kropka!
Jeśli tylko przewidujesz prawdopodobieństwo dla klasy dodatniej, to funkcję utraty logarytmicznej można obliczyć dla jednej prognozy klasyfikacji binarnej ( yhat ) w porównaniu do oczekiwanego prawdopodobieństwa ( y ) w następujący sposób:
yhatA = model.predict(X_validation)
print(yhatA[:12])
y_train[12]
# Classification Assessment
def Classification_Assessment(model ,Xtrain, ytrain, Xtest, ytest, y_pred):
import numpy as np
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.metrics import confusion_matrix, log_loss, auc, roc_curve, roc_auc_score, recall_score, precision_recall_curve
from sklearn.metrics import make_scorer, precision_score, fbeta_score, f1_score, classification_report
def green(text):
print('\033[32m', text, '\033[0m', sep='')
def blue(text):
print('\033[34m', text, '\033[0m', sep='')
print("Recall Training data: ", np.round(recall_score(ytrain, model.predict(Xtrain)), decimals=4))
print("Precision Training data: ", np.round(precision_score(ytrain, model.predict(Xtrain)), decimals=4))
print("----------------------------------------------------------------------")
print("Recall Test data: ", np.round(recall_score(ytest, model.predict(Xtest)), decimals=4))
print("Precision Test data: ", np.round(precision_score(ytest, model.predict(Xtest)), decimals=4))
print("----------------------------------------------------------------------")
print("Confusion Matrix Test data")
print(confusion_matrix(ytest, model.predict(Xtest)))
print("----------------------------------------------------------------------")
green('Valuation for test data only:')
print(classification_report(ytest, model.predict(Xtest)))
green('Valuation for test data only:')
y_pred_proba = model.predict_proba(Xtest)[::,1]
fpr, tpr, _ = metrics.roc_curve(ytest, y_pred)
auc = metrics.roc_auc_score(ytest, y_pred)
plt.plot(fpr, tpr, label='ROC (roc_auc = %0.2f)' % auc)
plt.xlabel('False Positive Rate',color='grey', fontsize = 13)
plt.ylabel('True Positive Rate',color='grey', fontsize = 13)
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")
plt.legend(loc=4)
plt.plot([0, 1], [0, 1],'r--')
plt.show()
print('roc_auc %.3f' % auc)
blue('---------------------')
AUC_train_1 = metrics.roc_auc_score(ytrain,model.predict_proba(Xtrain)[:,1])
blue('AUC_train: %.3f' % AUC_train_1)
AUC_test_1 = metrics.roc_auc_score(ytest,model.predict_proba(Xtest)[:,1])
blue('AUC_test: %.3f' % AUC_test_1)
blue('---------------------')
print("Accuracy Training data: ", np.round(accuracy_score(ytrain, model.predict(Xtrain)), decimals=4))
green("----------------------------------------------------------------------")
print("Accuracy Test data: ", np.round(accuracy_score(ytest, model.predict(Xtest)), decimals=4))
green("----------------------------------------------------------------------")
## colorful prints
def black(text):
print('\033[30m', text, '\033[0m', sep='')
def red(text):
print('\033[31m', text, '\033[0m', sep='')
def green(text):
print('\033[32m', text, '\033[0m', sep='')
def yellow(text):
print('\033[33m', text, '\033[0m', sep='')
def blue(text):
print('\033[34m', text, '\033[0m', sep='')
def magenta(text):
print('\033[35m', text, '\033[0m', sep='')
def cyan(text):
print('\033[36m', text, '\033[0m', sep='')
def gray(text):
print('\033[90m', text, '\033[0m', sep='')
blue(X_train.shape)
green(y_train.shape)
blue(X_validation.shape)
green(y_validation.shape)
Classification_Assessment(model,X_train, y_train, X_validation, y_validation, yhatA)
Dobrze jest zweryfikować swój model, ale zweryfikować go - nawet lepiej. A także z działkami! Bez słów:
cv_params = model.get_params()
cv_params
cv_params.update({'loss_function': 'Logloss'})
cv_data = cv(
Pool(X, y, cat_features=categorical_features_indices),
cv_params,
plot=True)
yhatCV = cv_data.predict(X_validation)
Teraz mamy wartości naszych funkcji strat na każdym etapie wzmocnienia uśrednione 3-krotnie, co powinno zapewnić nam dokładniejsze oszacowanie wydajności naszego modelu:
cv_data.head(2)
print('Best validation accuracy score: {:.2f}±{:.2f} on step {}'.format(
np.max(cv_data['test-Accuracy-mean']),
cv_data['test-Accuracy-std'][np.argmax(cv_data['test-Accuracy-mean'])],
np.argmax(cv_data['test-Accuracy-mean'])
))
np.max(cv_data['test-Accuracy-mean'])
np.argmax(cv_data['test-Accuracy-mean'])
print('Precise validation accuracy score: {}'.format(np.max(cv_data['test-Accuracy-mean'])))
Jak widzimy, nasze wstępne oszacowanie wydajności przy pojedynczym foldowaniu sprawdzania poprawności było zbyt optymistyczne - dlatego tak ważna jest krzyżowa weryfikacja!
Wszystko, co musisz zrobić, aby uzyskać prognozy, to
predictions = model.predict(X_validation)
predictions[:15]
predictions_probs = model.predict_proba(X_validation)
predictions_probs[:5]
Ale spróbujmy uzyskać lepsze prognozy, a funkcje Catboost nam w tym pomogą.
Być może zauważyłeś, że na etapie tworzenia modelu podałem nie tylko parametr custom_loss, ale także parametr random_seed. Zostało to zrobione, aby ten notatnik był odtwarzalny - domyślnie catboost wybiera losową wartość dla seed:
model_without_seed = CatBoostClassifier(iterations=10, logging_level='Silent')
model_without_seed.fit(X, y, cat_features=categorical_features_indices)
print('Random seed assigned for this model: {}'.format(model_without_seed.random_seed_))
Zdefiniujmy niektóre parametry i utwórz Pool dla większej wygody. Pool Przechowuje wszystkie informacje o zbiorze danych (cechy, etykiety, wskaźniki cech jakościowych, wagi i wiele innych).
To taki zbiornik z parametrami modelu
params = {
'iterations': 500,
'learning_rate': 0.1,
'eval_metric': 'Accuracy',
'random_seed': 42,
'logging_level': 'Silent',
'use_best_model': False
}
Pool dla zmiennych treningowych - to nie model, to taki zbiornik
train_pool = Pool(X_train, y_train, cat_features=categorical_features_indices)
train_pool
Pool dla zmiennych testowych - to nie model, to taki zbiornik
validate_pool = Pool(X_validation, y_validation, cat_features=categorical_features_indices)
validate_pool
Jeśli zasadniczo masz zestaw sprawdzania poprawności, zawsze lepiej jest używać parametru use_best_model podczas treningu. Domyślnie ten parametr jest włączony. Jeśli jest włączony, wynikowy zestaw drzew zmniejsza się do najlepszej iteracji.
## -------linijka jak wywołać najlepsze parametry modelu ---------------------
model = CatBoostClassifier(**params)
model.fit(train_pool, eval_set=validate_pool)
best_model_params = params.copy()
best_model_params.update({ ## <- tutaj model wkłada 'use_best_model'
'use_best_model': True ## to nie są lepsze parametry tylko ten jeden nowy parametr
})
### ----------------------------------------------------------------------------
best_model = CatBoostClassifier(**best_model_params)
best_model.fit(train_pool, eval_set=validate_pool);
print('Simple model validation accuracy: {:.4}'.format(
accuracy_score(y_validation, model.predict(X_validation))
))
print('')
print('Best model validation accuracy: {:.4}'.format(
accuracy_score(y_validation, best_model.predict(X_validation))
))
params
wyświetlam stare parametry modelu
params
wyświetlam nowe parametry modelu
best_model_params
best_model = CatBoostClassifier(**best_model_params)
best_model.fit(train_pool, eval_set=validate_pool,plot=True )
print('ZWYKŁY MODEL - Na zbiorze testowym accurace: ', accuracy_score(y_validation, model.predict(X_validation)))
print('NAJLEPSZY MODEL - Na zbiorze testowym accurace: ', accuracy_score(y_validation, best_model.predict(X_validation)))
y_bestPred = best_model.predict(X_validation)
Classification_Assessment(best_model,X_train, y_train, X_validation, y_validation, y_bestPred)
Jeśli zasadniczo masz zestaw sprawdzania poprawności, zawsze łatwiej i lepiej jest skorzystać z wczesnego zatrzymania. Ta funkcja jest podobna do poprzedniej, ale oprócz poprawy jakości wciąż oszczędza czas.
Czas robienia modelu bez 'earlystop'
%%time
model = CatBoostClassifier(**params)
model.fit(train_pool, eval_set=validate_pool)
Czas robienia modelu z 'earlystop'
%%time
earlystop_params = params.copy() #<-- tradycyjne dodawanie parametrów
earlystop_params.update({
'od_type': 'Iter',
'od_wait': 40
})
earlystop_model = CatBoostClassifier(**earlystop_params)
earlystop_model.fit(train_pool, eval_set=validate_pool)
Nowe parametry 'earlystop':
earlystop_params
print('Simple model tree count: {}'.format(model.tree_count_))
print('Simple model validation accuracy: {:.4}'.format(
accuracy_score(y_validation, model.predict(X_validation))
))
print('')
print('Early-stopped model tree count: {}'.format(earlystop_model.tree_count_))
print('Early-stopped model validation accuracy: {:.4}'.format(
accuracy_score(y_validation, earlystop_model.predict(X_validation))
))
Dzięki temu uzyskujemy lepszą jakość w krótszym czasie.
Chociaż, jak pokazano wcześniej, prosty schemat sprawdzania poprawności nie opisuje dokładnie wyniku poza zmiennymi treningowymi (może być tendencyjny z powodu podziału zestawu danych), nadal dobrze jest śledzić dynamikę ulepszeń modelu - a zatem, jak widać z tego przykładu, jest to naprawdę dobrze jest wcześniej zatrzymać proces wzmacniania (zanim rozpocznie się nadmierne dopasowanie)
Czyli model kończy się na najlepszym uzyskanym wyniku 'accuracy'
earlystop_model.fit(train_pool, eval_set=validate_pool, plot=True)
y_earlystop = earlystop_model.predict(X_validation)
Classification_Assessment(earlystop_model,X_train, y_train, X_validation, y_validation, y_earlystop)
Możliwe jest wykorzystanie wyników przedtreningowych (wyjściowych) do treningu.
Nie wiem po co to jest - daje słabe wyniki itd
current_params = params.copy()
current_params.update({
'iterations': 10
})
model = CatBoostClassifier(**current_params).fit(X_train, y_train, categorical_features_indices)
# Get baseline (only with prediction_type='RawFormulaVal')
baseline = model.predict(X_train, prediction_type='RawFormulaVal')
# Fit new model
model.fit(X_train, y_train, categorical_features_indices, baseline=baseline)
Znowu zmieniam parapetry dodaje jakiś parametr:'iterations': 10
model_cp = CatBoostClassifier(**current_params)
model_cp = model_cp.fit(X_train, y_train, categorical_features_indices)
Uzyskaj linię bazową (tylko z prediction_type = 'RawFormulaVal')
baseline = model_cp.predict(X_train, prediction_type='RawFormulaVal')
Fit new model
model_cp.fit(X_train, y_train, categorical_features_indices, baseline=baseline)
y_pred_cp = model_cp.predict(X_validation)
Classification_Assessment(model_cp,X_train, y_train, X_validation, y_validation, y_pred_cp)
Catboost obsługuje migawki. Możesz go użyć do odzyskania treningu po przerwie lub do rozpoczęcia treningu z wcześniejszymi wynikami.
params_with_snapshot = params.copy() #<-- tradycyjnie dodajemy nowe parametry
params_with_snapshot.update({
'iterations': 5,
'learning_rate': 0.5,
'logging_level': 'Verbose'
})
params_with_snapshot.update({ #<-- zmieniamy ustawienia migawki
'iterations': 10,
'learning_rate': 0.1,
})
Możliwe jest stworzenie własnej funkcji celu. Utwórzmy funkcję celu logloss.
przybliżenia, cele, wagi są indeksowanymi pojemnikami pływaków (pojemniki, które mają zdefiniowane tylko len i getitem). parametrem wag może być Brak. Aby zrozumieć, co oznaczają te parametry, załóż, że istnieje podzbiór zestawu danych, który jest obecnie przetwarzany. Program przybliża zawiera bieżące prognozy dla tego podzbioru, cele zawierają wartości docelowe podane w zestawie danych. Ta funkcja powinna zwrócić listę par (der1, der2), gdzie der1 jest pierwszą pochodną funkcji straty w odniesieniu do do przewidywanej wartości, a der2 jest drugą pochodną. W naszym przypadku logloss jest definiowany za pomocą następującej formuły: cel log (sigmoid (w przybliżeniu)) + (1 - cel) (1 - sigmoid (w przybliżeniu)) gdzie sigmoid (x) = 1 / (1 + e ^ (- x)).
class LoglossObjective(object):
def calc_ders_range(self, approxes, targets, weights):
# approxes, targets, weights are indexed containers of floats
# (containers which have only __len__ and __getitem__ defined).
# weights parameter can be None.
#
# To understand what these parameters mean, assume that there is
# a subset of your dataset that is currently being processed.
# approxes contains current predictions for this subset,
# targets contains target values you provided with the dataset.
#
# This function should return a list of pairs (der1, der2), where
# der1 is the first derivative of the loss function with respect
# to the predicted value, and der2 is the second derivative.
#
# In our case, logloss is defined by the following formula:
# target * log(sigmoid(approx)) + (1 - target) * (1 - sigmoid(approx))
# where sigmoid(x) = 1 / (1 + e^(-x)).
assert len(approxes) == len(targets)
if weights is not None:
assert len(weights) == len(approxes)
result = []
for index in range(len(targets)):
e = np.exp(approxes[index])
p = e / (1 + e)
der1 = (1 - p) if targets[index] > 0.0 else -p
der2 = -p * (1 - p)
if weights is not None:
der1 *= weights[index]
der2 *= weights[index]
result.append((der1, der2))
return result
model = CatBoostClassifier(
iterations=10,
random_seed=42,
loss_function=LoglossObjective(), ##<-- dodajemy własnoręcznie wymyśloną funkcję
eval_metric="Logloss"
)
# Fit model
model.fit(train_pool)
# Only prediction_type='RawFormulaVal' is allowed with custom `loss_function`
preds_raw = model.predict(X_validation, prediction_type='RawFormulaVal')
Możliwe jest również utworzenie własnej funkcji metrycznej. Utwórzmy funkcję metryczną logloss.
class LoglossMetric(object):
def get_final_error(self, error, weight):
return error / (weight + 1e-38)
def is_max_optimal(self):
return False
def evaluate(self, approxes, target, weight):
# approxes is a list of indexed containers
# (containers with only __len__ and __getitem__ defined),
# one container per approx dimension.
# Each container contains floats.
# weight is a one dimensional indexed container.
# target is float.
# weight parameter can be None.
# Returns pair (error, weights sum)
assert len(approxes) == 1
assert len(target) == len(approxes[0])
approx = approxes[0]
error_sum = 0.0
weight_sum = 0.0
for i in range(len(approx)):
w = 1.0 if weight is None else weight[i]
weight_sum += w
error_sum += -w * (target[i] * approx[i] - np.log(1 + np.exp(approx[i])))
return error_sum, weight_sum
model = CatBoostClassifier(
iterations=10,
random_seed=42,
loss_function="Logloss",
eval_metric=LoglossMetric()
)
# Fit model
model.fit(train_pool)
# Only prediction_type='RawFormulaVal' is allowed with custom `loss_function`
preds_raw = model.predict(X_validation, prediction_type='RawFormulaVal')
Model CatBoost ma metodę staged_predict. Pozwala iteracyjnie uzyskać prognozy dla danego zakresu drzew.
model_kot = CatBoostClassifier(iterations=10, random_seed=42, logging_level='Silent').fit(train_pool)
model_kot
określami ilość drzew
ntree_start, ntree_end, eval_period = 3, 9, 2
predictions_iterator
predictions_iterator = model.staged_predict(validate_pool, 'Probability', ntree_start, ntree_end, eval_period)
for preds, tree_count in zip(predictions_iterator, range(ntree_start, ntree_end, eval_period)):
print('First class probabilities using the first {} trees: {}'.format(tree_count, preds[:5, 1]))
Czasami bardzo ważne jest, aby zrozumieć, która funkcja miała największy wpływ na końcowy wynik. Aby to zrobić, model CatBoost ma metodę get_feature_importance.
Tworzy się taki model szkieletowy jak w poprzedniej metodzie
model = CatBoostClassifier(iterations=50, random_seed=42, logging_level='Silent').fit(train_pool)
Mówi się modelowi aby: 'get_feature_importance'
feature_importances = model.get_feature_importance(train_pool)
feature_names = X_train.columns
feature_names
for score, name in sorted(zip(feature_importances, feature_names), reverse=True):
print('{}: {}'.format(name, score))
To pokazuje, że funkcje Sex i Pclass miały największy wpływ na wynik.
co ciekawe wcale zadeklarowałem w 'train_pool', w które zmienne są dyskretne a model sam je sobie zcyfryzował
X_train['Ticket']
CatBoost ma metodę eval_metrics, która pozwala obliczyć dane metryki dla danego zestawu danych. I oczywiście je narysować :)
model = CatBoostClassifier(iterations=50, random_seed=42, logging_level='Silent').fit(train_pool)
eval_metrics = model.eval_metrics(validate_pool, ['AUC'], plot=True)
Można testować więcej wskaźników: https://catboost.ai/docs/search/?query=%27Accuracy%27
model = CatBoostClassifier(iterations=50, random_seed=42, logging_level='Silent').fit(train_pool)
eval_metrics = model.eval_metrics(validate_pool, ['Recall'], plot=True)
model = CatBoostClassifier(iterations=50, random_seed=42, logging_level='Silent').fit(train_pool)
eval_metrics = model.eval_metrics(validate_pool, ['Accuracy'], plot=True)
print(eval_metrics['Accuracy'][:16])
Możesz także porównać proces uczenia się różnych modeli na jednym wykresie.
model1 = CatBoostClassifier(iterations=1000, depth=1, train_dir='model_depth_1/', logging_level='Silent')
model1.fit(train_pool, eval_set=validate_pool)
model2 = CatBoostClassifier(iterations=1000, depth=5, train_dir='model_depth_5/', logging_level='Silent')
model2.fit(train_pool, eval_set=validate_pool);
from catboost import MetricVisualizer
widget = MetricVisualizer(['model_depth_1', 'model_depth_5'])
widget.start()
Zawsze bardzo przydatne jest zrzucenie modelu na dysk (szczególnie jeśli szkolenie zajęło trochę czasu).
model = CatBoostClassifier(iterations=10, random_seed=42, logging_level='Silent').fit(train_pool)
model.save_model('catboost_model.dump')
model = CatBoostClassifier()
model.load_model('catboost_model.dump');
Chociaż zawsze można wybrać optymalną liczbę iteracji (etapy przyspieszające) poprzez walidację krzyżową i wykresy krzywej uczenia się, ważne jest również, aby bawić się niektórymi parametrami modelu, i chcielibyśmy zwrócić szczególną uwagę na l2_leaf_reg i learning_rate.
W tej sekcji wybieramy te parametry za pomocą pakietu hyperopt.
Instalujemy to!
import hyperopt
def hyperopt_objective(params):
model = CatBoostClassifier(
l2_leaf_reg=int(params['l2_leaf_reg']),
learning_rate=params['learning_rate'],
iterations=500,
eval_metric='Accuracy',
random_seed=42,
verbose=False,
loss_function='Logloss',
)
cv_data = cv(
Pool(X, y, cat_features=categorical_features_indices),
model.get_params()
)
best_accuracy = np.max(cv_data['test-Accuracy-mean'])
return 1 - best_accuracy # as hyperopt minimises
from numpy.random import RandomState
params_space = {
'l2_leaf_reg': hyperopt.hp.qloguniform('l2_leaf_reg', 0, 2, 1),
'learning_rate': hyperopt.hp.uniform('learning_rate', 1e-3, 5e-1),
}
trials = hyperopt.Trials()
best = hyperopt.fmin(
hyperopt_objective,
space=params_space,
algo=hyperopt.tpe.suggest,
max_evals=50,
trials=trials,
rstate=RandomState(123)
)
print(best)
'l2_leaf_reg' Współczynnik na poziomie regularyzacji L2 funkcji kosztu. Każda wartość dodatnia jest dozwolona.
Domyślnie CatBoost buduje 1000 drzew. Liczbę iteracji można zmniejszyć, aby przyspieszyć trening.
Gdy liczba iteracji maleje, należy zwiększyć szybkość uczenia się. Domyślnie wartość szybkości uczenia się jest definiowana automatycznie w zależności od liczby iteracji i wejściowego zestawu danych. Zmiana liczby iteracji na mniejszą wartość jest dobrym punktem wyjścia do optymalizacji.
model = CatBoostClassifier(
l2_leaf_reg=int(best['l2_leaf_reg']),
learning_rate=best['learning_rate'],
iterations=500,
eval_metric='Accuracy',
random_seed=42,
verbose=False,
loss_function='Logloss',
)
cv_data = cv(Pool(X, y, cat_features=categorical_features_indices), model.get_params())
print('Precise validation accuracy score: {}'.format(np.max(cv_data['test-Accuracy-mean'])))
Przypomnijmy, że przy domyślnych parametrach wynik cv wyniósł 0,8283, a zatem mamy (prawdopodobnie nieistotną statystycznie) pewną poprawę.
Teraz zmienilibyśmy nasz dostrojony model na wszystkich danych treningowych, które mamy
model_VV.fit(X, y, cat_features=categorical_features_indices)
Na koniec przygotujmy plik zgłoszenia:
import pandas as pd
submisstion = pd.DataFrame()
#submisstion['PassengerId'] = X_train['PassengerId']
#submisstion['Survived'] = model.predict(X_train)
submisstion.to_csv('submission.csv', index=False)
Wreszcie możesz złożyć zgłoszenie w konkursie Titanic Kaggle.
Otóż to! Teraz możesz grać z CatBoost i wygrywać niektóre konkursy! :)